#include "app_pool.h"

#define APP_POOL_MQ_NAME "/pool_mq"

typedef struct
{
    void (*task)(void *);
    void *arg;
} app_pool_task_t;

typedef struct
{
    int thread_num;     // 线程池中线程的数量
    pthread_t *threads; // 存储所有线程的id

    mqd_t mq; // 消息队列id
    char *mq_name;
} app_pool_t;

static app_pool_t my_pool;



void *thread_fun(void *arg);
gate_status_t app_pool_init(int thread_num)
{
    my_pool.thread_num = thread_num;
    // 动态分配一个数组
    my_pool.threads = malloc(thread_num * sizeof(pthread_t));
    if (my_pool.threads == NULL)
    {
        perror("线程池内存分配失败导致线程池创建失败");
        return ERROR;
    }

    // 创建 thread_num 个线程
    for (size_t i = 0; i < thread_num; i++)
    {
        int r = pthread_create(&my_pool.threads[i], NULL, thread_fun, NULL);
        if (r != 0)
        {
            perror("线程池中线程创建失败导致线程池创建失败");
            return ERROR;
        }
    }

    // 初始化消息队列
    my_pool.mq_name = APP_POOL_MQ_NAME;
    mq_unlink(my_pool.mq_name); // 删除已存在的消息队列
    struct mq_attr attr;
    attr.mq_maxmsg = thread_num;               // 消息队列的最大消息数
    attr.mq_msgsize = sizeof(app_pool_task_t); // 单个消息的大小 TODO: 待完善
    attr.mq_flags = 0;                         // 阻塞式消息队列
    my_pool.mq = mq_open(my_pool.mq_name, O_RDWR | O_CREAT, 0666, &attr);
    if (my_pool.mq == (mqd_t)-1)
    {
        perror("消息队列创建失败,导致线程池创建失败");
        return ERROR;
    }

    log_info("线程池初始化成功");

    return OK;
}

void app_pool_deInit(void)
{
    // 所有线程退出
    for (size_t i = 0; i < my_pool.thread_num; i++)
    {
        pthread_cancel(my_pool.threads[i]);
    }

    // 关闭消息队列和删除消息队列
    mq_close(my_pool.mq);
    mq_unlink(my_pool.mq_name);

    // 释放线程资源
    free(my_pool.threads);
}

/**
 * @brief 添加任务
 *
 * @param task 任务函数
 * @param arg 任务参数
 */
gate_status_t app_pool_add_task(void (*task)(void *), void *arg)
{
    if (task == NULL)
    {
        log_error("任务函数不能为空");
        return ERROR;
    }

    app_pool_task_t pool_task = {.task = task, .arg = arg};
    if (mq_send(my_pool.mq, (char *)&pool_task, sizeof(app_pool_task_t), 0) == -1)
    {
        perror("任务添加失败");
        return ERROR;
    }
    log_debug("任务添加成功");
    return OK;
}

void *thread_fun(void *arg)
{
    while (1)
    {
        app_pool_task_t task;
        ssize_t real_len = mq_receive(my_pool.mq, (char *)&task, sizeof(app_pool_task_t), NULL);
        if (real_len == sizeof(app_pool_task_t) && task.task) // 读到消息
        {
            task.task(task.arg);
        }
    }
}
